package cn.gok.oa.system.service.impl;

import cn.gok.oa.system.dto.RoleDto;
import cn.gok.oa.system.dto.RoleListDto;
import cn.gok.oa.system.entity.TbMenu;
import cn.gok.oa.system.entity.TbMenuRole;
import cn.gok.oa.system.entity.TbRole;
import cn.gok.oa.system.entity.TbUser;
import cn.gok.oa.system.mapper.TbMenuRoleMapper;
import cn.gok.oa.system.mapper.TbRoleMapper;
import cn.gok.oa.system.mapper.TbUserMapper;
import cn.gok.oa.system.service.ITbRoleService;
import com.alibaba.fastjson.JSONObject;
import com.auth0.jwt.JWT;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author gok
 * @since 2022-08-04
 */
@Service
public class TbRoleServiceImpl extends ServiceImpl<TbRoleMapper, TbRole> implements ITbRoleService {

    @Autowired
    TbRoleMapper tbRoleMapper;

    @Autowired
    TbMenuRoleMapper tbMenuRoleMapper;

    @Autowired
    TbUserMapper tbUserMapper;


    @Override
    public IPage<TbRole> info(RoleListDto roleListDto) {
        Page<TbRole> page = new Page<>(roleListDto.getPage(), roleListDto.getLimit());
        // 组装查询条件
        QueryWrapper<TbRole> queryWrapper = new QueryWrapper<>();
        queryWrapper.like(StringUtils.isNotBlank(roleListDto.getRoleName()),"name",roleListDto.getRoleName());
        return tbRoleMapper.selectPage(page,queryWrapper);
    }

    @Override
    @Transactional
    public void addRole(RoleDto roleDto, HttpServletRequest httpServletRequest) {
        // 获取token中的userId
        String token = httpServletRequest.getHeader("token");
        Integer userId = Integer.parseInt(JWT.decode(token).getAudience().get(0));
        // 增加角色表name remark creat_id字段
        // 增加菜单角色关系表的role_id menu_id creat_id remark
        TbRole role = new TbRole();
        TbMenuRole tbMenuRole = new TbMenuRole();
        // 将roleDto中与TbRole相同的字段赋值插入role表
        BeanUtils.copyProperties(roleDto,role);
        role.setCreateId(userId);
        int insert = tbRoleMapper.insert(role);
        // 根据角色名称获取角色id
        QueryWrapper<TbRole> roleWrapper = new QueryWrapper();
        roleWrapper.lambda().eq(TbRole::getName,roleDto.getName());
        Integer roleId = tbRoleMapper.selectOne(roleWrapper).getId();
        // 遍历菜单列表并插入菜单角色关系表
        int insert1 = 0;
        ArrayList<TbMenuRole> tbMenuRoles = new ArrayList<>();
        for (Integer menuId: roleDto.getMenuId()){
            tbMenuRole.setRoleId(roleId);
            tbMenuRole.setMenuId(menuId);
            tbMenuRole.setCreateId(userId);
            tbMenuRole.setRemark(roleDto.getRemarkMenuRole());
            tbMenuRoles.add(tbMenuRole);
            insert1 = tbMenuRoleMapper.insert(tbMenuRole);
        }
//        int insert1 = tbMenuRoleMapper.insert(tbMenuRole);
        if (insert>0 && insert1>0){
            return;
        } throw new RuntimeException("插入异常，回滚");
    }


    @Override
    @Transactional
    public void deleteRole(Integer roleId, HttpServletRequest httpServletRequest) {
        String token = httpServletRequest.getHeader("token");
        Integer userId = Integer.parseInt(JWT.decode(token).getAudience().get(0));
        // 判断roleId是否已分配 分配则不可删除
        QueryWrapper<TbUser> userWrapper = new QueryWrapper<>();
        userWrapper.lambda().eq(TbUser::getRoleId,roleId);
        TbUser tbUser = tbUserMapper.selectOne(userWrapper);
        // 判断角色是否已被分配菜单权限 未分配则不用进行菜单角色关系表的删除
        QueryWrapper<TbMenuRole> menuRoleQueryWrapper = new QueryWrapper<>();
        menuRoleQueryWrapper.lambda().eq(TbMenuRole::getRoleId,roleId);
        List<TbMenuRole> isTbMenuRole = tbMenuRoleMapper.selectList(menuRoleQueryWrapper);

        if (null == tbUser){
            // 删除角色表
            TbRole role = tbRoleMapper.selectById(roleId).setModifyId(userId);
            int i = tbRoleMapper.updateById(role);
            int i1 = tbRoleMapper.deleteById(roleId);
            int i2 = 0;
            if (isTbMenuRole.isEmpty()){
                i2 = 1;
            } else {
                // 删除菜单角色关系表
                TbMenuRole tbMenuRole = new TbMenuRole();
                Map<String, Object> map = new HashMap<>();
                map.put("role_id",roleId);
                i2 = tbMenuRoleMapper.deleteByMap(map);
            }
            if (i>0 && i1>0 && i2>0){
                return;
            } throw new RuntimeException("删除异常,回滚！");
        } throw new RuntimeException("删除异常,角色id已分配！");
    }


    @Override
    @Transactional
    public void updateRole(RoleDto roleDto, HttpServletRequest httpServletRequest) {
        String token = httpServletRequest.getHeader("token");
        Integer userId = Integer.parseInt(JWT.decode(token).getAudience().get(0));
        // 更新角色表
        UpdateWrapper<TbRole> roleUpdateWrapper = new UpdateWrapper<>();
        roleUpdateWrapper
                .set("name",roleDto.getName())
                .set("modify_id",userId)
                .set("remark",roleDto.getRemark())
                .eq("id",roleDto.getId());
        int update = tbRoleMapper.update(null, roleUpdateWrapper);

        // 更新菜单角色关系表(删除已有菜单并重新插入)
        Map<String, Object> map = new HashMap<>();
        map.put("role_id",roleDto.getId());
        // 改角色id下若无可用菜单 则会显示修改失败
        int i = tbMenuRoleMapper.deleteByMap(map);

        // 存在则恢复 不存在则添加
        TbMenuRole tbMenuRole = new TbMenuRole();
        ArrayList<TbMenuRole> tbMenuRoles = new ArrayList<>();
        int insert = 0;
        for (Integer menuId: roleDto.getMenuId()){
            insert = tbMenuRoleMapper.recoveryByMenuId(menuId,roleDto.getId(),userId);
            if (insert == 0){
                tbMenuRole.setRoleId(roleDto.getId());
                tbMenuRole.setMenuId(menuId);
                tbMenuRole.setCreateId(userId);
                tbMenuRole.setRemark(roleDto.getRemarkMenuRole());
                tbMenuRoles.add(tbMenuRole);
                insert = tbMenuRoleMapper.insert(tbMenuRole);
            }
        }
        if (update>0 && i>0 && insert>0){
            return;
        } throw new RuntimeException("更新异常,回滚！");

    }
}
